#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
股票名称审计工具
用于检查和诊断股票名称映射问题，确保数据质量
"""

import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from modules.stock_name_validator import get_stock_name_validator, StockNameValidator
import yaml
import json
from typing import Dict, List, Set
from datetime import datetime

class StockNameAuditor:
    """股票名称审计器"""
    
    def __init__(self):
        self.validator = get_stock_name_validator()
        self.config_path = 'config/stocks.yaml'
        self.audit_results = {}
        
    def load_config_stocks(self) -> List[str]:
        """加载配置文件中的股票代码"""
        try:
            with open(self.config_path, 'r', encoding='utf-8') as f:
                config = yaml.safe_load(f)
            return config.get('a_stocks', [])
        except Exception as e:
            print(f"加载配置文件失败: {e}")
            return []
    
    def audit_config_consistency(self) -> Dict[str, any]:
        """审计配置文件一致性"""
        print("🔍 审计配置文件一致性...")
        
        config_stocks = self.load_config_stocks()
        config_codes = []
        
        for stock_entry in config_stocks:
            if isinstance(stock_entry, str):
                stock_code = stock_entry.strip().strip("'\"")
                config_codes.append(stock_code)
        
        # 检查重复
        duplicates = []
        seen = set()
        for code in config_codes:
            if code in seen:
                duplicates.append(code)
            seen.add(code)
        
        # 检查格式（支持6位数字股票代码和指数代码如000001.SH）
        format_issues = []
        for code in config_codes:
            # 标准6位股票代码
            is_stock_code = code.isdigit() and len(code) == 6
            # 指数代码（如000001.SH, 000001.SZ）
            is_index_code = ('.' in code and 
                           code.split('.')[0].isdigit() and 
                           len(code.split('.')[0]) == 6 and
                           code.split('.')[1] in ['SH', 'SZ'])
            
            if not (is_stock_code or is_index_code):
                format_issues.append(code)
        
        results = {
            "total_stocks": len(config_codes),
            "unique_stocks": len(seen),
            "duplicates": duplicates,
            "format_issues": format_issues,
            "status": "✅ 通过" if not duplicates and not format_issues else "⚠️ 有问题"
        }
        
        self.audit_results['config_consistency'] = results
        return results
    
    def audit_name_coverage(self) -> Dict[str, any]:
        """审计名称覆盖情况"""
        print("🔍 审计股票名称覆盖情况...")
        
        config_stocks = self.load_config_stocks()
        config_codes = [stock.strip().strip("'\"") for stock in config_stocks if isinstance(stock, str)]
        
        validated_results = self.validator.batch_validate(config_codes)
        
        coverage_stats = {
            "config_source": 0,
            "manual_source": 0, 
            "default_source": 0,
            "high_confidence": 0,
            "medium_confidence": 0,
            "low_confidence": 0
        }
        
        missing_names = []
        low_confidence_names = []
        
        for code, stock_info in validated_results.items():
            # 来源统计
            if stock_info.source == "config":
                coverage_stats["config_source"] += 1
            elif stock_info.source == "manual":
                coverage_stats["manual_source"] += 1
            elif stock_info.source == "default":
                coverage_stats["default_source"] += 1
                missing_names.append({"code": code, "name": stock_info.name})
            
            # 置信度统计
            if stock_info.confidence >= 0.8:
                coverage_stats["high_confidence"] += 1
            elif stock_info.confidence >= 0.6:
                coverage_stats["medium_confidence"] += 1
            else:
                coverage_stats["low_confidence"] += 1
                low_confidence_names.append({
                    "code": code, 
                    "name": stock_info.name, 
                    "confidence": stock_info.confidence
                })
        
        results = {
            "coverage_stats": coverage_stats,
            "missing_names": missing_names,
            "low_confidence_names": low_confidence_names,
            "coverage_rate": (coverage_stats["config_source"] + coverage_stats["manual_source"]) / len(config_codes) * 100,
            "status": "✅ 良好" if coverage_stats["low_confidence"] == 0 else "⚠️ 需要改进"
        }
        
        self.audit_results['name_coverage'] = results
        return results
    
    def audit_name_accuracy(self) -> Dict[str, any]:
        """审计名称准确性（基于已知的正确映射）"""
        print("🔍 审计股票名称准确性...")
        
        # 已知准确的股票名称映射（可以从权威数据源获取）
        known_accurate = {
            "000001": "平安银行",
            "000001.SH": "上证指数",
            "000001.SZ": "平安银行",  # 错误格式，实际应该是000001
            "000975": "山金国际", 
            "000426": "兴业银锡",
            "600019": "宝钢股份",
            "601611": "中国核建",
            "002162": "悦心健康",
            "512660": "军工ETF",
            "510050": "上证50ETF",
            "510300": "沪深300ETF",
            "159922": "中证500ETF"
        }
        
        validated_results = self.validator.batch_validate(list(known_accurate.keys()))
        
        accuracy_issues = []
        correct_count = 0
        
        for code, expected_name in known_accurate.items():
            if code in validated_results:
                actual_name = validated_results[code].name
                if actual_name == expected_name:
                    correct_count += 1
                else:
                    accuracy_issues.append({
                        "code": code,
                        "expected": expected_name,
                        "actual": actual_name,
                        "source": validated_results[code].source
                    })
        
        accuracy_rate = correct_count / len(known_accurate) * 100
        
        results = {
            "total_checked": len(known_accurate),
            "correct_count": correct_count,
            "accuracy_rate": accuracy_rate,
            "accuracy_issues": accuracy_issues,
            "status": "✅ 准确" if accuracy_rate >= 95 else "⚠️ 需要修正"
        }
        
        self.audit_results['name_accuracy'] = results
        return results
    
    def generate_recommendations(self) -> List[Dict[str, str]]:
        """生成改进建议"""
        recommendations = []
        
        # 基于审计结果生成建议
        if 'config_consistency' in self.audit_results:
            config_results = self.audit_results['config_consistency']
            if config_results.get('duplicates'):
                recommendations.append({
                    "type": "配置文件问题",
                    "priority": "高",
                    "description": f"发现重复的股票代码: {', '.join(config_results['duplicates'])}",
                    "action": "移除配置文件中的重复条目"
                })
            
            if config_results.get('format_issues'):
                recommendations.append({
                    "type": "格式问题",
                    "priority": "中",
                    "description": f"发现格式异常的股票代码: {', '.join(config_results['format_issues'])}",
                    "action": "确保所有股票代码为6位数字，或指数代码格式如000001.SH"
                })
        
        if 'name_coverage' in self.audit_results:
            coverage_results = self.audit_results['name_coverage']
            if coverage_results.get('missing_names'):
                recommendations.append({
                    "type": "名称缺失",
                    "priority": "中",
                    "description": f"有 {len(coverage_results['missing_names'])} 个股票使用默认名称",
                    "action": "在配置文件中添加正确的股票名称注释"
                })
        
        if 'name_accuracy' in self.audit_results:
            accuracy_results = self.audit_results['name_accuracy']
            if accuracy_results.get('accuracy_issues'):
                recommendations.append({
                    "type": "名称错误",
                    "priority": "高",
                    "description": f"发现 {len(accuracy_results['accuracy_issues'])} 个股票名称不准确",
                    "action": "修正股票名称映射表中的错误条目"
                })
        
        return recommendations
    
    def run_full_audit(self) -> Dict[str, any]:
        """运行完整审计"""
        print("📊 开始股票名称完整审计...\n")
        
        # 执行各项审计
        config_results = self.audit_config_consistency()
        coverage_results = self.audit_name_coverage()
        accuracy_results = self.audit_name_accuracy()
        
        # 生成建议
        recommendations = self.generate_recommendations()
        
        # 汇总结果
        summary = {
            "audit_time": datetime.now().isoformat(),
            "overall_status": "✅ 良好" if not recommendations else "⚠️ 需要改进",
            "config_consistency": config_results,
            "name_coverage": coverage_results,
            "name_accuracy": accuracy_results,
            "recommendations": recommendations,
            "total_issues": len(recommendations)
        }
        
        return summary
    
    def print_audit_report(self, results: Dict[str, any]):
        """打印审计报告"""
        print("\n" + "="*60)
        print("📊 股票名称审计报告")
        print("="*60)
        
        print(f"审计时间: {results['audit_time']}")
        print(f"总体状态: {results['overall_status']}")
        print(f"发现问题: {results['total_issues']} 个")
        
        print("\n📋 配置文件一致性:")
        config = results['config_consistency']
        print(f"  状态: {config['status']}")
        print(f"  总股票数: {config['total_stocks']}")
        print(f"  唯一股票数: {config['unique_stocks']}")
        if config.get('duplicates'):
            print(f"  重复代码: {', '.join(config['duplicates'])}")
        if config.get('format_issues'):
            print(f"  格式问题: {', '.join(config['format_issues'])}")
        
        print("\n📊 名称覆盖情况:")
        coverage = results['name_coverage']
        print(f"  状态: {coverage['status']}")
        print(f"  覆盖率: {coverage['coverage_rate']:.1f}%")
        print(f"  高置信度: {coverage['coverage_stats']['high_confidence']} 个")
        print(f"  中置信度: {coverage['coverage_stats']['medium_confidence']} 个")
        print(f"  低置信度: {coverage['coverage_stats']['low_confidence']} 个")
        
        print("\n🎯 名称准确性:")
        accuracy = results['name_accuracy']
        print(f"  状态: {accuracy['status']}")
        print(f"  准确率: {accuracy['accuracy_rate']:.1f}%")
        print(f"  已检查: {accuracy['total_checked']} 个")
        print(f"  正确数量: {accuracy['correct_count']} 个")
        
        if results['recommendations']:
            print("\n💡 改进建议:")
            for i, rec in enumerate(results['recommendations'], 1):
                print(f"  {i}. [{rec['priority']}] {rec['description']}")
                print(f"     建议: {rec['action']}")
        
        print("\n" + "="*60)

def main():
    """主函数"""
    auditor = StockNameAuditor()
    results = auditor.run_full_audit()
    auditor.print_audit_report(results)
    
    # 保存审计结果
    with open('audit_report.json', 'w', encoding='utf-8') as f:
        json.dump(results, f, ensure_ascii=False, indent=2)
    
    print(f"\n📄 详细审计结果已保存到: audit_report.json")

if __name__ == "__main__":
    main() 